Trading





Kerry Back

Steps

  • Generate current predictions as in the previous session to obtain a dataframe indexed by ticker with a “predict” column.
  • Add information from Alpaca
    • tradable and shortable status
    • bid and ask prices
    • current positions

  • For longs, choose the best tradable stocks.
  • For shorts, choose the worst shortable stocks.
  • To equal weight, set target weights = 1/numstocks.
  • Target $ values are equity * target weights.
  • Target shares are target $ values / prices.
  • Trades are target shares - current shares.

Example

  • 150/50
  • Longs = 100 best tradable stocks equally weighted
  • Shorts = 100 worst shortable stocks equally weighted
  • Target dollars:
    • Longs = 0.015 * equity
    • Shorts = 0.005 * equity
  • Trades = (target dollars - current dollars) / ask or bid

Tradable and shortable

from alpaca.trading.client import TradingClient

trading_client = TradingClient(KEY, SECRET_KEY, paper=True)
assets = trading_client.get_all_assets()

df["tradable"] = {
  x.symbol: x.tradable for x in assets
}

df["shortable"] = {
  x.symbol: x.shortable for x in assets
}

Quotes

from alpaca.data import StockHistoricalDataClient
from alpaca.data.requests import StockLatestQuoteRequest

data_client = StockHistoricalDataClient(KEY, SECRET_KEY)
params = StockLatestQuoteRequest(
  symbol_or_symbols=df.index.to_list()
)
quotes = data_client.get_stock_latest_quote(params)

df["ask"] = {x: quotes[x].ask_price for x in quotes}
df["bid"] = {x: quotes[x].bid_price for x in quotes}

Account equity and current positions

account = trading_client.get_account()
equity = float(account.equity)

current = trading_client.get_all_positions()
df["current"] = (
    {x.symbol: int(x.qty) for x in current} 
    if len(current)>0 else 0
)
df["current"] = df.current.fillna(0)

Ranking tradables and shortables

df["predict"] = np.where(
  df.tradable & (df.ask>0), 
  df.predict, np.nan
)
df["rank_from_top"] = df.predict.rank(
  ascending=False, 
  method="first
)

df["predict"] = np.where(
  df.shortable & (df.bid>0), 
  df.predict, np.nan
)
df["rank_from_bottom"] = df.predict.rank(method="first")

Longs and shorts

numlong = numshort = 100

df["long"] = df.rank_from_top <= numlong
df["short"] = df.rank_from_bottom <= numshort

print(f"number long is {len(df.long)}")
print(f"number short is {len(df.short)}")

Targets and trades

df["target_dollars"] = (
  (1.5*equity/numlong)*df.long - 
      (0.5*equity/numshort)*df.short
)
df["current_dollars"] = df.current*(df.bid+df.ask)/2
df["trade_dollars"] = df.target_dollars - df.current_dollars
df["trade"] = (
    (df.trade_dollars>0)*df.trade_dollars/df.ask
    + (df.trade_dollars<0)*df.trade_dollars/df.bid
)
df["trade"] = df.trade.fillna(0)
df["trade"] = df.trade.astype(int)

Submit buys

for tick in df[df.trade>0].index:
  try:
    market_order_data = MarketOrderRequest(
      symbol=tick,
      qty=df.trade[tick],
      side=OrderSide.BUY,
      time_in_force=TimeInForce.DAY
    )
    market_order = trading_client.submit_order(
      order_data=market_order_data
    )
  except:
    print(f"buy order for {tick} failed")

Submit sells

for tick in df[df.trade<0].index:
  try:
    market_order_data = MarketOrderRequest(
      symbol=tick,
      qty=abs(df.trade[tick]),
      side=OrderSide.SELL,
      time_in_force=TimeInForce.DAY
    )
    market_order = trading_client.submit_order(
      order_data=market_order_data
    )
  except:
    print(f"sell order for {tick} failed")

Save data

  • df
  • trades
  • new positions
  • account equity
  • See binder notebook for an example.